package com.ruoyi.project.monitor.controller

import com.ruoyi.common.constant.*
import com.ruoyi.common.exception.job.TaskException
import com.ruoyi.common.utils.job.CronUtils
import com.ruoyi.common.utils.job.ScheduleUtils
import com.ruoyi.common.utils.poi.ExcelUtil
import com.ruoyi.framework.aspectj.lang.annotation.*
import com.ruoyi.framework.aspectj.lang.enums.BusinessType
import com.ruoyi.framework.web.controller.BaseController
import com.ruoyi.framework.web.domain.AjaxResult
import com.ruoyi.framework.web.page.TableDataInfo
import com.ruoyi.project.monitor.domain.SysJob
import com.ruoyi.project.monitor.service.ISysJobService
import org.apache.commons.lang3.StringUtils
import org.quartz.SchedulerException
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import javax.servlet.http.HttpServletResponse

/**
 * 调度任务信息操作处理
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/job")
open class SysJobController : BaseController() {
    @Autowired
    private val jobService: ISysJobService? = null

    /**
     * 查询定时任务列表
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:list')")
    @GetMapping("/list")
    fun list(sysJob: SysJob?): TableDataInfo {
        startPage()
        val list = jobService!!.selectJobList(sysJob)
        return getDataTable(list)
    }

    /**
     * 导出定时任务列表
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:export')")
    @Log(title = "定时任务", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    fun export(response: HttpServletResponse, sysJob: SysJob) {
        val list = jobService!!.selectJobList(sysJob)
        val util = ExcelUtil(SysJob::class.java)
        util.exportExcel(response, list, "定时任务")
    }

    /**
     * 获取定时任务详细信息
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:query')")
    @GetMapping(value = ["/{jobId}"])
    fun getInfo(@PathVariable("jobId") jobId: Long?): AjaxResult {
        return AjaxResult.success(jobService!!.selectJobById(jobId))
    }

    /**
     * 新增定时任务
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:add')")
    @Log(title = "定时任务", businessType = BusinessType.INSERT)
    @PostMapping
    @Throws(
            SchedulerException::class, TaskException::class
    )
    fun add(@RequestBody job: SysJob): AjaxResult {
        when {
            !CronUtils.isValid(job.cronExpression) -> {
                return error("新增任务'" + job.jobName + "'失败，Cron表达式不正确")
            }
            StringUtils.containsIgnoreCase(job.invokeTarget, Constants.LOOKUP_RMI) -> {
                return error("新增任务'" + job.jobName + "'失败，目标字符串不允许'rmi'调用")
            }
            com.ruoyi.common.utils.StringUtils.containsAnyIgnoreCase(
                    job.invokeTarget,
                    *arrayOf(Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS)
            )
            -> {
                return error("新增任务'" + job.jobName + "'失败，目标字符串不允许'ldap(s)'调用")
            }
            com.ruoyi.common.utils.StringUtils.containsAnyIgnoreCase(
                    job.invokeTarget,
                    *arrayOf(Constants.HTTP, Constants.HTTPS)
            )
            -> {
                return error("新增任务'" + job.jobName + "'失败，目标字符串不允许'http(s)'调用")
            }
            com.ruoyi.common.utils.StringUtils.containsAnyIgnoreCase(
                    job.invokeTarget,
                    *Constants.JOB_ERROR_STR
            )
            -> {
                return error("新增任务'" + job.jobName + "'失败，目标字符串存在违规")
            }
            !ScheduleUtils.whiteList(job.invokeTarget) -> {
                return error("新增任务'" + job.jobName + "'失败，目标字符串不在白名单内")
            }
            else -> {
                job.createBy = username
                return toAjax(jobService!!.insertJob(job))
            }
        }
    }

    /**
     * 修改定时任务
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:edit')")
    @Log(title = "定时任务", businessType = BusinessType.UPDATE)
    @PutMapping
    @Throws(
            SchedulerException::class, TaskException::class
    )
    fun edit(@RequestBody job: SysJob): AjaxResult {
        when {
            !CronUtils.isValid(job.cronExpression) -> {
                return error("修改任务'" + job.jobName + "'失败，Cron表达式不正确")
            }
            StringUtils.containsIgnoreCase(job.invokeTarget, Constants.LOOKUP_RMI) -> {
                return error("修改任务'" + job.jobName + "'失败，目标字符串不允许'rmi'调用")
            }
            com.ruoyi.common.utils.StringUtils.containsAnyIgnoreCase(
                    job.invokeTarget,
                    *arrayOf(Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS)
            )
            -> {
                return error("修改任务'" + job.jobName + "'失败，目标字符串不允许'ldap(s)'调用")
            }
            com.ruoyi.common.utils.StringUtils.containsAnyIgnoreCase(
                    job.invokeTarget,
                    *arrayOf(Constants.HTTP, Constants.HTTPS)
            )
            -> {
                return error("修改任务'" + job.jobName + "'失败，目标字符串不允许'http(s)'调用")
            }
            com.ruoyi.common.utils.StringUtils.containsAnyIgnoreCase(
                    job.invokeTarget,
                    *Constants.JOB_ERROR_STR
            )
            -> {
                return error("修改任务'" + job.jobName + "'失败，目标字符串存在违规")
            }
            !ScheduleUtils.whiteList(job.invokeTarget) -> {
                return error("修改任务'" + job.jobName + "'失败，目标字符串不在白名单内")
            }
            else -> {
                job.updateBy = username
                return toAjax(jobService!!.updateJob(job))
            }
        }
    }

    /**
     * 定时任务状态修改
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
    @Log(title = "定时任务", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    @Throws(
            SchedulerException::class
    )
    fun changeStatus(@RequestBody job: SysJob): AjaxResult {
        val newJob = jobService!!.selectJobById(job.jobId)
        newJob.status = job.status
        return toAjax(jobService.changeStatus(newJob))
    }

    /**
     * 定时任务立即执行一次
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
    @Log(title = "定时任务", businessType = BusinessType.UPDATE)
    @PutMapping("/run")
    @Throws(
            SchedulerException::class
    )
    fun run(@RequestBody job: SysJob): AjaxResult {
        val result = jobService!!.run(job)
        return if (result) success() else error("任务不存在或已过期！")
    }

    /**
     * 删除定时任务
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
    @Log(title = "定时任务", businessType = BusinessType.DELETE)
    @DeleteMapping("/{jobIds}")
    @Throws(
            SchedulerException::class, TaskException::class
    )
    fun remove(@PathVariable jobIds: Array<Long?>): AjaxResult {
        jobService!!.deleteJobByIds(jobIds)
        return success()
    }
}
